import Base2DPainter from "./Base2DPainter";
import Point3D from "../Point/Point3D";
import Point2D from "../Point/Point2D";
import eUtils from '../../utils/every-utils';

export default class Base3DPainter extends Base2DPainter {

    constructor(canvas) {
        super(canvas);
    }

    /**
     * @param shape3d {Shape3D}
     * @param beforeDrawSurface {Function=}
     */
    drawShape3D(shape3d, beforeDrawSurface) {
        shape3d.startDataInit();
        let no = 0;
        while (shape3d.hasNextSurface()) {
            let surface = shape3d.nextSurfaceData();
            this.drawInSession(() => {
                surface.points.forEach((point, i) => {
                    let point2d = this.getLikePointFrom3D(point);
                    if (i === 0) {
                        this.beginPath();
                        this.moveTo(point2d.x, point2d.y);
                        return;
                    }
                    this.lineTo(point2d.x, point2d.y);
                });
                this.closePath();
                if (eUtils.isFunction(beforeDrawSurface)) {
                    beforeDrawSurface.call(this, surface, no++);
                }
            });
        }
    }

    getEyePoint() {
        return this.canvas.eyePoint;
    }

    /**
     * @param point3D {Point3D}
     */
    getLikePointFrom3D(point3D) {
        let planeZ = 0;

        let eyePoint = this.getEyePoint();
        // let scale = eyePoint.z / (eyePoint.z + point3D.z);

        let eye2projection = new Point2D(eyePoint.x, eyePoint.y);
        let point2projection = new Point2D(point3D.x, point3D.y);

        let eyeVertDistance = eyePoint.getDistanceFromAnotherPoint(
            new Point3D(eyePoint.x, eyePoint.y, planeZ)
        );

        let asbPointVertDistance = point3D.getDistanceFromAnotherPoint(
            new Point3D(point3D.x, point3D.y, planeZ)
        );

        let pointVertDistance = point3D.z >= planeZ ? asbPointVertDistance : -asbPointVertDistance;

        let eye2pointDistance = eyePoint.getDistanceFromAnotherPoint(point3D);

        let lessDistance = pointVertDistance * eye2pointDistance / (eyeVertDistance - pointVertDistance);

        let projectionDistance = eye2projection.getDistanceFromAnotherPoint(point2projection);

        let projectionLessDistance = Math.sqrt(Math.pow(lessDistance, 2) - Math.pow(pointVertDistance, 2));

        let displacement = point3D.z >= planeZ ? (projectionDistance + projectionLessDistance) :
            (projectionDistance - projectionLessDistance);


        let angle2d = eye2projection['getDegFromAnotherPoint'](point2projection);

        // console.log('============================');
        // console.log('eyeVertDistance', eyeVertDistance);
        // console.log('pointVertDistance', pointVertDistance);
        // console.log('eye2pointDistance', eye2pointDistance);
        // console.log('lessDistance', lessDistance);
        // console.log('projectionDistance', projectionDistance);
        // console.log('projectionLessDistance', projectionLessDistance);
        // console.log('displacement', displacement);
        // console.log('angle2d', angle2d);

        // return new Point2D(point3D.x * scale, point3D.y * scale);
        let resultPoint = eye2projection['getOtherPointFromDistanceAndDeg'](displacement, angle2d);
        let screenCentre = new Point2D(this.canvas.width / 2, this.canvas.height / 2);
        resultPoint.x += screenCentre.x - eyePoint.x;
        resultPoint.y += screenCentre.y - eyePoint.y;
        return resultPoint;
    }

}